Serverless Framework+TypeScriptのプロジェクトでnode_modulesをAWS Lambda Layers化しよう
こんにちは。サービスグループの武田です。
先日Serverless Framework+JavaScript環境に、serverless-layersプラグインを導入し、お手軽にnode_modulesをLambda Layers化しました。
Serverless Frameworkのserverless-layersプラグインを使って超お手軽にnode_modulesをAWS Lambda Layers化する
今回は同様のことを、TypeScript(+webpack)の環境でもやってみました。
検証環境
次のような環境で検証しています。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G103 $ node -v v10.16.3 $ npm ls serverless serverless-layers example-serverless-ts@1.0.0 /path/to/example-serverless-ts ├── serverless@1.53.0 └── serverless-layers@1.4.2
Lambdaのランタイムはnodejs10.x
です。またAWSにデプロイするためのIAMなどは用意されていることとします。
やってみた
プロジェクト作成
さっそくプロジェクトを作っていきます。テンプレートにaws-nodejs-typescript
を指定すると、TypeScriptが使える環境で作成されます。
$ npx -p serverless sls create -t aws-nodejs-typescript -p example-serverless-ts $ cd $_ && npm install && npm install -D serverless $ npx sls invoke local -f hello { "statusCode": 200, "body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!\",\n \"input\": \"\"\n}" }
またデプロイ先を東京リージョンにするため、provider.region
を追記しておきます。
provider: name: aws runtime: nodejs10.x region: ap-northeast-1
次にmomentとunderscore.stringをインストールし、モジュールを使うようにhandler.js
を少し改造します。
$ npm install moment underscore.string
import { APIGatewayProxyHandler } from 'aws-lambda'; import * as moment from 'moment'; import { prune } from 'underscore.string'; import 'source-map-support/register'; export const hello: APIGatewayProxyHandler = async (event, _context) => { return { statusCode: 200, body: JSON.stringify({ message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!' + prune(moment().format(), 12), input: event, }, null, 2), }; }
確認のため、もう一度ローカル実行してみます。
$ npx sls invoke local -f hello { "statusCode": 200, "body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!2019-10-02T...\",\n \"input\": \"\"\n}" }
問題なく実行できました。
Layer化せずにデプロイ
Layer化した後とのサイズが比較できるように、一度そのままデプロイしてみます。
$ npx sls deploy ... Serverless: Uploading service example-serverless-ts.zip file to S3 (366.21 KB)... $ npx sls invoke -f hello { "statusCode": 200, "body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!2019-10-02T...\",\n \"input\": {}\n}" }
366.21 KB というサイズでした。実行も問題なくできています。マネジメントコンソールにアクセスしてデプロイされたファイルを確認してみたところ、次のようになっていました。
serverless-layersを導入してデプロイ
続いてserverless-layersを導入していきます。前回とほぼ同じ手順ですが、今回はwebpackのビルド対象からnode_modulesを除外する必要があります。
- Lambda Layersデプロイ用のS3バケットを用意
- serverless-layersプラグインをインストール
- 設定ファイルに設定を追加
- webpackの設定変更
1の手順は省略します。ここではバケット名をlambda-layers-deploy-123456789012
としておきます。
次にsls plugin install
でプラグインをインストールします。
$ npx sls plugin install --name serverless-layers
先ほど作成したバケットを設定ファイルに追加します。
custom: serverless-layers: layersDeploymentBucket: lambda-layers-deploy-123456789012
node_modulesをwebpackのビルド対象から除外します。
$ npm install -D webpack-node-externals
const path = require('path'); const slsw = require('serverless-webpack'); const nodeExternals = require('webpack-node-externals'); module.exports = { mode: slsw.lib.webpack.isLocal ? 'development' : 'production', entry: slsw.lib.entries, devtool: 'source-map', resolve: { extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], }, output: { libraryTarget: 'commonjs', path: path.join(__dirname, '.webpack'), filename: '[name].js', }, target: 'node', module: { rules: [ // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader` { test: /\.tsx?$/, loader: 'ts-loader' }, ], }, externals: [nodeExternals()], };
以上で必要な変更は完了です。デプロイしてみましょう。
$ npx sls deploy Serverless: [LayersPlugin]: Downloading package.json from bucket... Serverless: [LayersPlugin]: package.json does not exists at bucket... Serverless: [LayersPlugin]: Dependencies has changed! Re-installing... ... Serverless: Uploading service example-serverless-ts.zip file to S3 (3.25 KB)... $ npx sls invoke -f hello { "statusCode": 200, "body": "{\n \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!2019-10-02T...\",\n \"input\": {}\n}" }
Lambda本体は 3.25 KB とかなり軽量化されました。マネジメントコンソールでファイルを確認すると、きちんと依存モジュールが除外されていることも確認できました。
まとめ
Serverless Framework+TypeScriptの環境でserverless-layersを試してみました。webpackの設定変更が若干見落としがちになりそうです(というか見落としてました)。それではよいServerless生活を!